볼트 in 쿠버네티스
개요
쿠버네티스에서 볼트를 활용하는 방법에 대해 알아보자.
일단 이 방식은 볼트를 클러스터에 설치한 상황을 이야기한다.
흔히 헬름으로 설치한 상황으로 받아들이면 되겠다.
볼트에서는 클러스터에서 볼트를 효율적으로 활용할 수 있도록 세 가지 정도의 통합 방식을 지원한다.
Agent Injector
워크로드가 볼트의 시크릿을 사용해야 하는 경우 사용하는 방식이다.
에이전트를 워크로드의 사이드카로 주입하여 이 에이전트가 시크릿을 받아오는 역할을 수행하게 한다.
보다시피 Mutating Admission Webhook으로 사이드카가 파드에 주입되고, 이 파드가 각종 볼트에서 시크릿을 가져오는 역할을 수행한다.
사이드카 인젝터가 동작하게 하려면 어노테이션 세팅을 해주면 된다.
vault.hashicorp.com/agent-inject: true
vault.hashicorp.com/agent-inject-secret-<unique-name>: /path/to/secret
vault.hashicorp.com/agent-inject-template-foo: |
{{- with secret "database/creds/db-app" -}}
postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/mydb?sslmode=disable
{{- end }}
vault.hashicorp.com/role: 'db-app'
이런 식으로 필요한 스펙들을 전부 어노테이션으로 넣어준다..
dp-app이란 앱롤을 이용할 거고, <unique-name>
의 시크릿을 어떤 경로에 넣으라는 식이다.
넣을 때는 위처럼 템플릿 형태로 넣는 것도 가능하다.
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
config.hcl: |
"auto_auth" = {
"method" = {
"config" = {
"role" = "db-app"
}
"type" = "kubernetes"
}
"sink" = {
"config" = {
"path" = "/home/vault/.token"
}
"type" = "file"
}
}
"exit_after_auth" = false
"pid_file" = "/home/vault/.pid"
"template" = {
"contents" = "{{- with secret \"database/creds/db-app\" -}}postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/mydb?sslmode=disable{{- end }}"
"destination" = "/vault/secrets/db-creds"
}
"vault" = {
"address" = "https://vault.demo.svc.cluster.local:8200"
"ca_cert" = "/vault/tls/ca.crt"
"client_cert" = "/vault/tls/client.crt"
"client_key" = "/vault/tls/client.key"
}
이런 식으로 원하는 설정을 ConfigMap으로 만든 후에 이걸 어노테이션으로 명시하는 것도 가능하다.
vault.hashicorp.com/agent-configmap: 'my-configmap'
이런 식으로 말이다.
Vault Secret Operator
Vault Secret Operator는 말 그대로 볼트를 오퍼레이터로 만들어낸 것이다.
Vault CSI Provider
볼트를 CSI로 활용하는 방식!
이것도 어플리케이션 레벨에서 보면 위의 에이전트 인젝팅 방식보다 조금 더 번거로울 수도 있는 방식.
대신에 이번에는 워크로드마다 에이전트가 주입되는 것이 아니라 노드의 데몬셋으로 스토리지 프로바이더가 배포돼 있고, 파드에서 이걸 스토리지로서 활용하면 해당 시크릿을 가져와서 넣어주는 방식이다.
이 시크릿은 쿠버의 시크릿으로서 만들어져서 파드에 마운팅되는데, 이건 처음 봤지만 시크릿을 csi로 사용하는 방식이 또 있나보다.[1]
개인적으로 평하자면, 에이전트 주입 방식은 프로세스가 더 띄워지는 격이므로 컴퓨팅 리소스를 조금 더 소모한다는 점에서 아쉽다.
그러나 위 방식은 쿠버의 시크릿으로서 데이터를 불필요하게 클러스터에 잠시라도 남겨야만 하고, 모든 노드의 데몬셋 파드가 띄워져 있어야만 한다는 점에서 에이전트 주입 방식보다 더 아쉽게 느껴진다.
최소한 에이전트는 프로세스가 떠 있는 만큼 토큰 갱신이라던가 하는 작업을 잘 해줄 수 있지만, CSI 방식은 그런 것도 없는 것으로 보인다.
이 방식이 좋을 수 있는 경우는 다른 사이드카가 볼트를 활용하는 경우가 아닐까 하는 생각이 들었는데, 사이드카 컨테이너를 이용하면 사실 컨테이너 순서 보장도 가능해서 굳이..?
apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
name: vault-db-creds
spec:
provider: vault
parameters:
roleName: 'app'
objects: |
- objectName: "dbUsername"
secretPath: "database/creds/db-app"
secretKey: "username"
- objectName: "dbPassword"
secretPath: "database/creds/db-app"
secretKey: "password"
아무튼 이렇게 먼저 시크릿 프로바이더 클래스를 지정한다.
volumes:
- name: vault-db-creds
csi:
driver: 'secrets-store.csi.k8s.io'
readOnly: true
volumeAttributes:
secretProviderClass: 'vault-db-creds'
그 다음에 워크로드에서는 이렇게 csi 임시 볼륨 형태로 사용한다.
관련 문서
이름 | noteType | created |
---|---|---|
볼트 in 쿠버네티스 | knowledge | 2025-04-14 |
Vault Secret Operator | knowledge | 2025-04-14 |
10W - Vault를 활용한 CICD 보안 | published | 2025-04-16 |
7W - 이스티오 메시 스케일링 | published | 2025-06-09 |
E-이스티오 메시 스케일링 | topic/explain | 2025-06-08 |